﻿using Nop.Admin.Models.Common;
using Nop.Admin.Models.XJ;
using Nop.Core;
using Nop.Core.Domain.Customers;
using Nop.Core.Domain.XJ;
using Nop.Services.Catalog;
using Nop.Services.Common;
using Nop.Services.Customers;
using Nop.Services.Directory;
using Nop.Services.ExportImport;
using Nop.Services.Logging;
using Nop.Services.Media;
using Nop.Services.Security;
using Nop.Services.XJ;
using Nop.Web.Framework.Controllers;
using Nop.Web.Framework.Kendoui;
using Nop.Web.Framework.Mvc;
using System;
using System.Linq;
using System.Web.Mvc;

namespace Nop.Admin.Controllers
{
	public class EquipmentStockOutController : BaseAdminController
	{
		#region Fields
		private readonly IPermissionService _permissionService;
		private readonly IPictureService _pictureService;
		private readonly IWorkContext _workContext;
		private readonly IOrganizationService _organizationServce;
		private readonly IDepartmentService _departmentService;
		private readonly ICustomerService _customerService;
		private readonly IGenericAttributeService _genericAttributeService;
		private readonly IXJPlaceService _xjPlaceService;
		private readonly IXJEquipmentCategoryService _xJEquipmentCategoryService;
		private readonly IXJEquipmentService _xJEquipmentService;
		private readonly IXJEquipmentStockService _xJEquipmentStockService;
		private readonly IXJEquipmentStockLogService _xJEquipmentStockLogService;
		private readonly IXJEquipmentStockInService _xJEquipmentStockInService;
		private readonly IXJEquipmentStockInDetailService _xJEquipmentStockInDetailService;
		private readonly IXJEquipmentStockOutService _xJEquipmentStockOutService;
		private readonly IXJEquipmentStockOutDetailService _xJEquipmentStockOutDetailService;
		private readonly IXJInspectionService _xJInspectionService;
		private readonly IXJInspectionPlanService _xJInspectionPlanService;
		private readonly IXJMaintenanceService _xJMaintenanceService;
		private readonly IXJMaintenanceCommentService _xJMaintenanceCommentService;
		private readonly ICustomerActivityService _customerActivityService;
		private readonly IExportManager _exportManager;
		private readonly ILogger _logger;
		#endregion

		#region Constructors
		public EquipmentStockOutController(IPermissionService permissionService,
			IPictureService pictureService,
			IWorkContext workContext,
			IOrganizationService organizationServce,
			IDepartmentService departmentService,
			ICustomerService customerService,
			IGenericAttributeService genericAttributeService,
			IXJPlaceService xjPlaceService,
			IXJEquipmentCategoryService xJEquipmentCategoryService,
			IXJEquipmentService xJEquipmentService,
			IXJEquipmentStockService xJEquipmentStockService,
			IXJEquipmentStockLogService xJEquipmentStockLogService,
			IXJEquipmentStockInService xJEquipmentStockInService,
			IXJEquipmentStockInDetailService xJEquipmentStockInDetailService,
			IXJEquipmentStockOutService xJEquipmentStockOutService,
			IXJEquipmentStockOutDetailService xJEquipmentStockOutDetailService,
			IXJInspectionService xJInspectionService,
			IXJInspectionPlanService xJInspectionPlanService,
			IXJMaintenanceService xJMaintenanceService,
			IXJMaintenanceCommentService xJMaintenanceCommentService,
			ICustomerActivityService customerActivityService,
			IExportManager exportManager,
			ILogger logger)
		{
			this._permissionService = permissionService;
			this._pictureService = pictureService;
			this._workContext = workContext;
			this._organizationServce = organizationServce;
			this._departmentService = departmentService;
			this._customerService = customerService;
			this._genericAttributeService = genericAttributeService;
			this._xjPlaceService = xjPlaceService;
			this._xJEquipmentCategoryService = xJEquipmentCategoryService;
			this._xJEquipmentService = xJEquipmentService;
			this._xJEquipmentStockService = xJEquipmentStockService;
			this._xJEquipmentStockLogService = xJEquipmentStockLogService;
			this._xJEquipmentStockInService = xJEquipmentStockInService;
			this._xJEquipmentStockInDetailService = xJEquipmentStockInDetailService;
			this._xJEquipmentStockOutService = xJEquipmentStockOutService;
			this._xJEquipmentStockOutDetailService = xJEquipmentStockOutDetailService;
			this._xJInspectionService = xJInspectionService;
			this._xJInspectionPlanService = xJInspectionPlanService;
			this._xJMaintenanceService = xJMaintenanceService;
			this._xJMaintenanceCommentService = xJMaintenanceCommentService;
			this._customerActivityService = customerActivityService;
			this._exportManager = exportManager;
			this._logger = logger;
		}
		#endregion

		#region Untilities

		[NonAction]
		private int GetDays(DateTime? startOn, DateTime? endOn)
		{
			if (startOn.HasValue && endOn.HasValue)
			{
				TimeSpan timeSpan = endOn.Value.Subtract(startOn.Value);
				return (int)Math.Round(timeSpan.TotalDays, 0);
			}
			return 0;
		}

		[NonAction]
		protected virtual void PrepareAllCategoriesModel(EquipmentStockOutModel model)
		{
			if (model == null)
				throw new ArgumentNullException("model");

			var places = _xjPlaceService.GetAllPlaces(showHidden: false);
			foreach (var p in places)
				model.AvailablePlaces.Add(new SelectListItem { Text = p.Name, Value = p.Id.ToString() });

		}

		#endregion

		#region List
		public ActionResult Index()
		{
			return RedirectToAction("List");
		}

		public virtual ActionResult List()
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageOuts))
				return AccessDeniedView();

			var model = new EquipmentStockOutListModel();
			model.AvailableStates.Add(new SelectListItem
			{
				Text = "全部",
				Value = "0"
			});
			Type enumInspectionType = typeof(StockOutStateEnum);
			Enum.GetNames(enumInspectionType).ToList().ForEach(s =>
			{
				string value = Enum.Format(enumInspectionType, Enum.Parse(enumInspectionType, s), "d");
				model.AvailableStates.Add(new SelectListItem { Text = s, Value = value });
			});
			model.AvailableUsers.Add(new SelectListItem
			{
				Text = "全部",
				Value = "0"
			});
			var users = _customerService.GetAllCustomers(customerRoleIds: new[] { _customerService.GetCustomerRoleBySystemName(SystemCustomerRoleNames.Repairman).Id }).Select(x => new { id = x.Id, name = x.TrueName ?? x.Username }).ToList();
			foreach (var item in users)
				model.AvailableUsers.Add(new SelectListItem { Text = item.name, Value = item.id.ToString() });
			return View(model);
		}

		[HttpPost]
		public virtual ActionResult List(DataSourceRequest command, EquipmentStockOutListModel model)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageOuts))
				return AccessDeniedKendoGridJson();

			var customer = _workContext.CurrentCustomer;
			if (customer.IsAdmin() || customer.IsKeyLeader() || customer.IsResponsibleLeader() || customer.IsWarehouseKeeper())
			{
				var outs = _xJEquipmentStockOutService.GetAllStockOuts(
					sNo: model.SearchSNo,
					wNo: model.SearchWNo,
					departmentId: model.SearchDepartmentId,
					customerId: model.SearchUserId,
					pageIndex: command.Page - 1,
					pageSize: command.PageSize);
				var gridModel = new DataSourceResult
				{
					Data = outs.Select(x =>
					{
						var categoryModel = new EquipmentStockOutModel
						{
							Id = x.Id,
							SNo = x.SNo,
							CustomerId = x.CustomerId,
							CreatedOn = x.CreatedOn,
							State = x.State,
							StateName = Enum.GetName(typeof(StockOutStateEnum), x.State)
						};
						return categoryModel;
					}),
					Total = outs.TotalCount
				};
				return Json(gridModel);
			}
			else if (customer.IsDepartmentManager() && customer.DepartmentId > 0)
			{
				var outs = _xJEquipmentStockOutService.GetAllStockOuts(
					sNo: model.SearchSNo,
					wNo: model.SearchWNo,
					departmentId: customer.DepartmentId,
					pageIndex: command.Page - 1,
					pageSize: command.PageSize);
				var gridModel = new DataSourceResult
				{
					Data = outs.Select(x =>
					{
						var categoryModel = new EquipmentStockOutModel
						{
							Id = x.Id,
							SNo = x.SNo,
							CustomerId = x.CustomerId,
							CreatedOn = x.CreatedOn,
							State = x.State,
							StateName = Enum.GetName(typeof(StockOutStateEnum), x.State)
						};
						return categoryModel;
					}),
					Total = outs.TotalCount
				};
				return Json(gridModel);
			}
			else
			{
				var outs = _xJEquipmentStockOutService.GetAllStockOuts(
					sNo: model.SearchSNo,
					wNo: model.SearchWNo,
					customerId: customer.Id,
					pageIndex: command.Page - 1,
					pageSize: command.PageSize);
				var gridModel = new DataSourceResult
				{
					Data = outs.Select(x =>
					{
						var categoryModel = new EquipmentStockOutModel
						{
							Id = x.Id,
							SNo = x.SNo,
							CustomerId = x.CustomerId,
							CreatedOn = x.CreatedOn,
							State = x.State,
							StateName = Enum.GetName(typeof(StockOutStateEnum), x.State)
						};
						return categoryModel;
					}),
					Total = outs.TotalCount
				};
				return Json(gridModel);
			}
		}

		#endregion

		#region Create / Edit / Delete

		public virtual ActionResult Create(int maintenanceId = 0)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageOuts))
				return AccessDeniedView();

			var customer = _workContext.CurrentCustomer;
			if (null != customer)
			{
				var stockOut = _xJEquipmentStockOutService.GetStockOutByCustomerId(customer.Id);
				if (null != stockOut && !stockOut.Deleted)
				{
					if (maintenanceId != stockOut.MaintenanceId)
					{
						stockOut.MaintenanceId = maintenanceId;
						_xJEquipmentStockOutService.UpdateXJEquipmentStockOut(stockOut);
					}
					return RedirectToAction("Edit", new { id = stockOut.Id });
				}
				else
				{
					stockOut = new XJEquipmentStockOut
					{
						SNo = _xJEquipmentStockOutService.GenerateNo(),
						MaintenanceId = maintenanceId,
						State = (int)StockOutStateEnum.保存,
						CustomerId = customer.Id,
						CustomerName = customer.TrueName,
						DepartmentId = customer.DepartmentId,
						DepartmentName = customer.DepartmentName,
						CreatedOn = DateTime.Now,
					};
					_xJEquipmentStockOutService.InsertXJEquipmentStockOut(stockOut);
					_customerActivityService.InsertActivity("AddNewEquipmentStockOut", "新增出库记录：{0}", stockOut.Id);
					return RedirectToAction("Edit", new { id = stockOut.Id });
				}
			}

			var model = new EquipmentStockOutModel
			{
				SNo = _xJEquipmentStockOutService.GenerateNo(),
				CustomerId = customer.Id,
				CustomerName = customer.TrueName,
				DepartmentName = customer.DepartmentName,
				CreatedOn = DateTime.Now,
			};
			//categories
			PrepareAllCategoriesModel(model);

			return View(model);
		}

		[HttpPost, ParameterBasedOnFormName("save-continue", "continueEditing")]
		public virtual ActionResult Create(EquipmentStockOutModel model, bool continueEditing)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageOuts))
				return AccessDeniedView();

			var customer = _workContext.CurrentCustomer;
			if (ModelState.IsValid)
			{
				if (!continueEditing)
				{
					if (model.Id == 0 || !_xJEquipmentStockOutDetailService.GetAllStockOutDetails(outId: model.Id).Any())
					{
						ErrorNotification("不能提交");
						return View(model);
					}
				}
				var resultDetail = _xJEquipmentStockOutDetailService.Verify(outId: model.Id);
				if (!resultDetail.Result)
				{
					ErrorNotification(resultDetail.Msg);
					return View(model);
				}
				int state = (int)StockOutStateEnum.保存;
				// 默认由部门领导审核，没有部门的直接仓管确认出库
				if (!continueEditing)
					state = customer.DepartmentId == 0 ? (int)StockOutStateEnum.待出库 : (int)StockOutStateEnum.待审核;
				var stockOut = new XJEquipmentStockOut
				{
					MaintenanceId = model.MaintenanceId,
					SNo = _xJEquipmentStockOutService.GenerateNo(),
					State = state,
					CustomerId = customer.Id,
					CustomerName = customer.TrueName,
					DepartmentId = customer.DepartmentId,
					DepartmentName = customer.DepartmentName,
					CreatedOn = DateTime.Now,
				};
				_xJEquipmentStockOutService.InsertXJEquipmentStockOut(stockOut);

				//activity log
				_customerActivityService.InsertActivity("AddNewEquipmentStockOut", "新增出库记录：{0}", stockOut.Id);
				// 同步冻结数量
				_xJEquipmentService.SyncAmount(customer: customer, syncFreeze: true);
				SuccessNotification("保存成功");

				if (continueEditing)
				{
					//selected tab
					SaveSelectedTabName();

					return RedirectToAction("Edit", new { id = stockOut.Id });
				}
				return RedirectToAction("List");
			}

			return View(model);
		}

		public virtual ActionResult Edit(int id)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageOuts))
				return AccessDeniedView();

			var stockOut = _xJEquipmentStockOutService.GetXJEquipmentStockOutById(id);
			if (stockOut == null || stockOut.Deleted)
				//No equipment found with the specified id
				return RedirectToAction("List");
			if (stockOut.State > (int)StockOutStateEnum.待审核)
			{
				ErrorNotification("不能编辑");
				return RedirectToAction("List");
			}

			var model = new EquipmentStockOutModel
			{
				Id = stockOut.Id,
				MaintenanceId = stockOut.MaintenanceId,
				SNo = stockOut.SNo,
				State = stockOut.State,
				CustomerId = stockOut.CustomerId,
				CustomerName = stockOut.CustomerName,
				DepartmentName = stockOut.DepartmentName,
				CreatedOn = stockOut.CreatedOn,
			};
			//categories
			PrepareAllCategoriesModel(model);

			return View(model);
		}

		[HttpPost, ParameterBasedOnFormName("save-continue", "continueEditing")]
		public virtual ActionResult Edit(EquipmentStockOutModel model, bool continueEditing)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageOuts))
				return AccessDeniedView();

			var stockOut = _xJEquipmentStockOutService.GetXJEquipmentStockOutById(model.Id);
			if (stockOut == null || stockOut.Deleted)
				//No equipment found with the specified id
				return RedirectToAction("List");
			if (stockOut.State > (int)StockOutStateEnum.待审核)
			{
				ErrorNotification("不能编辑");
				return View(model);
			}

			if (ModelState.IsValid)
			{
				var customer = _workContext.CurrentCustomer;
				if (!continueEditing && !_xJEquipmentStockOutDetailService.GetAllStockOutDetails(outId: model.Id).Any())
				{
					ErrorNotification("不能提交");
					return View(model);
				}
				var resultDetail = _xJEquipmentStockOutDetailService.Verify(outId: model.Id);
				if (!resultDetail.Result)
				{
					ErrorNotification(resultDetail.Msg);
					return View(model);
				}

				int state = (int)StockOutStateEnum.保存;
				// 默认由部门领导审核，没有部门的直接仓管确认出库
				if (!continueEditing)
					state = customer.DepartmentId == 0 ? (int)StockOutStateEnum.待出库 : (int)StockOutStateEnum.待审核;
				stockOut.State = state;
				_xJEquipmentStockOutService.UpdateXJEquipmentStockOut(stockOut);

				//activity log
				_customerActivityService.InsertActivity("EditStockOut", "编辑出库记录：{0}", stockOut.Id);
				// 同步冻结数量
				_xJEquipmentService.SyncAmount(customer: customer, syncFreeze: true);
				SuccessNotification("保存成功");
				if (continueEditing)
				{
					//selected tab
					SaveSelectedTabName();

					return RedirectToAction("Edit", new { id = stockOut.Id });
				}
				return RedirectToAction("List");
			}
			//categories
			PrepareAllCategoriesModel(model);

			return View(model);
		}

		public virtual ActionResult View(int id)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageOuts))
				return AccessDeniedView();

			var stockOut = _xJEquipmentStockOutService.GetXJEquipmentStockOutById(id);
			if (stockOut == null || stockOut.Deleted)
				//No equipment found with the specified id
				return RedirectToAction("List");

			var model = new EquipmentStockOutModel
			{
				Id = stockOut.Id,
				MaintenanceId = stockOut.MaintenanceId,
				SNo = stockOut.SNo,
				Reviewer = stockOut.Reviewer,
				ReviewOn = stockOut.ReviewOn,
				Keeper = stockOut.Keeper,
				KeeperOn = stockOut.KeeperOn,
				State = stockOut.State,
				CustomerId = stockOut.CustomerId,
				CustomerName = stockOut.CustomerName,
				DepartmentName = stockOut.DepartmentName,
				CreatedOn = stockOut.CreatedOn,
			};
			return View(model);
		}

		public virtual ActionResult Audit(int id)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageOuts))
				return AccessDeniedView();

			var stockOut = _xJEquipmentStockOutService.GetXJEquipmentStockOutById(id);
			if (stockOut == null || stockOut.Deleted)
				//No equipment found with the specified id
				return RedirectToAction("List");

			var model = new EquipmentStockOutModel
			{
				Id = stockOut.Id,
				MaintenanceId = stockOut.MaintenanceId,
				SNo = stockOut.SNo,
				Reviewer = stockOut.Reviewer,
				ReviewOn = stockOut.ReviewOn,
				Keeper = stockOut.Keeper,
				KeeperOn = stockOut.KeeperOn,
				State = stockOut.State,
				CustomerId = stockOut.CustomerId,
				CreatedOn = stockOut.CreatedOn,
			};
			return View(model);
		}

		[HttpPost, ParameterBasedOnFormName("save-pass", "pass")]
		public virtual ActionResult Audit(EquipmentStockOutModel model, bool pass)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageOuts))
				return AccessDeniedView();

			var stockOut = _xJEquipmentStockOutService.GetXJEquipmentStockOutById(model.Id);
			if (stockOut == null || stockOut.Deleted)
				//No equipment found with the specified id
				return RedirectToAction("List");
			if (stockOut.State != (int)StockInStateEnum.待审核)
			{
				ErrorNotification("无需审核");
				return View(model);
			}
			var customer = _workContext.CurrentCustomer;
			if (!customer.IsAdmin() && !(customer.IsDepartmentManager() && customer.DepartmentId == stockOut.DepartmentId))
			{
				ErrorNotification("不能审核");
				return View(model);
			}

			stockOut.Reviewer = customer.TrueName;
			stockOut.ReviewOn = DateTime.Now;
			stockOut.State = pass ? (int)StockOutStateEnum.待出库 : (int)StockOutStateEnum.驳回;
			_xJEquipmentStockOutService.UpdateXJEquipmentStockOut(stockOut);
			//activity log
			_customerActivityService.InsertActivity("AuditStockOut", "审核出库记录：{0}", stockOut.Id);

			SuccessNotification("操作成功");
			return RedirectToAction("List");
		}

		public virtual ActionResult Out(int id)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageOuts))
				return AccessDeniedView();

			var stockOut = _xJEquipmentStockOutService.GetXJEquipmentStockOutById(id);
			if (stockOut == null || stockOut.Deleted)
				//No equipment found with the specified id
				return RedirectToAction("List");

			var model = new EquipmentStockOutModel
			{
				Id = stockOut.Id,
				MaintenanceId = stockOut.MaintenanceId,
				SNo = stockOut.SNo,
				Reviewer = stockOut.Reviewer,
				ReviewOn = stockOut.ReviewOn,
				Keeper = stockOut.Keeper,
				KeeperOn = stockOut.KeeperOn,
				State = stockOut.State,
				CustomerId = stockOut.CustomerId,
				CreatedOn = stockOut.CreatedOn,
			};
			return View(model);
		}

		[HttpPost, ParameterBasedOnFormName("save-pass", "pass")]
		public virtual ActionResult Out(EquipmentStockOutModel model, bool pass)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageOuts))
				return AccessDeniedView();

			var customer = _workContext.CurrentCustomer;

			if (ModelState.IsValid)
			{
				var result = _xJEquipmentStockOutService.Out(model.Id, pass, customer);
				if (!result.Result)
				{
					ErrorNotification(result.Msg ?? "不能出库");
					return View(model);
				}
				//activity log
				_customerActivityService.InsertActivity("ConfirmStockOut", "确认出库记录：{0}", model.Id);

				SuccessNotification("操作成功");
				return RedirectToAction("List");
			}
			return View(model);
		}

		[HttpPost]
		public virtual ActionResult Delete(int id)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageOuts))
				return AccessDeniedView();

			var stockOut = _xJEquipmentStockOutService.GetXJEquipmentStockOutById(id);
			if (stockOut == null)
				//No equipment found with the specified id
				return RedirectToAction("List");

			_xJEquipmentStockOutService.DeleteXJEquipmentStockOut(stockOut);

			//activity log
			_customerActivityService.InsertActivity("DeleteStockOut", "删除出库记录：{0}", stockOut.Id);

			SuccessNotification("删除成功");
			return RedirectToAction("List");
		}

		#endregion

		#region Detail

		[HttpPost]
		public virtual ActionResult DetailList(DataSourceRequest command, EquipmentStockOutListModel model)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageOuts) && !_permissionService.Authorize(StandardPermissionProvider.ManageMaintenances) && !_permissionService.Authorize(StandardPermissionProvider.ManageMyMaintenances))
				return AccessDeniedKendoGridJson();

			var customer = _workContext.CurrentCustomer;

			if (customer.IsAdmin() || customer.IsKeyLeader() || customer.IsResponsibleLeader() || customer.IsWarehouseKeeper())
			{
				var outs = _xJEquipmentStockOutDetailService.GetEquipmentStockOutDetails(
					maintenanceId: model.SearchMaintenanceId,
					equipmentId: model.SearchEquipmentId,
					departmentId: model.SearchDepartmentId,
					customerId: model.SearchUserId,
					sno: model.SearchSNo,
					wno: model.SearchWNo,
					name: model.SearchName,
					startOn: model.SearchStartOn,
					endOn: model.SearchEndOn,
					state: model.SearchState,
					pageIndex: command.Page - 1,
					pageSize: command.PageSize);
				var total = _xJEquipmentStockOutDetailService.GetTotal(
					maintenanceId: model.SearchMaintenanceId,
					equipmentId: model.SearchEquipmentId,
					departmentId: model.SearchDepartmentId,
					customerId: model.SearchUserId,
					sno: model.SearchSNo,
					wno: model.SearchWNo,
					name: model.SearchName,
					startOn: model.SearchStartOn,
					endOn: model.SearchEndOn,
					state: model.SearchState
					);
				var gridModel = new DataSourceResult
				{
					ExtraData = total,
					Data = outs.Select(x =>
					{
						x.StateName = Enum.GetName(typeof(StockOutStateEnum), x.State);
						x.Total = x.Amount * x.Price;
						return x;
					}),
					Total = outs.TotalCount
				};
				return Json(gridModel);
			}
			else if (customer.IsDepartmentManager() && customer.DepartmentId > 0)
			{
				var outs = _xJEquipmentStockOutDetailService.GetEquipmentStockOutDetails(
					maintenanceId: model.SearchMaintenanceId,
					equipmentId: model.SearchEquipmentId,
					departmentId: customer.DepartmentId,
					customerId: model.SearchUserId,
					sno: model.SearchSNo,
					wno: model.SearchWNo,
					name: model.SearchName,
					startOn: model.SearchStartOn,
					endOn: model.SearchEndOn,
					state: model.SearchState,
					pageIndex: command.Page - 1,
					pageSize: command.PageSize);
				var total = _xJEquipmentStockOutDetailService.GetTotal(
					maintenanceId: model.SearchMaintenanceId,
					equipmentId: model.SearchEquipmentId,
					departmentId: customer.DepartmentId,
					customerId: model.SearchUserId,
					sno: model.SearchSNo,
					wno: model.SearchWNo,
					name: model.SearchName,
					startOn: model.SearchStartOn,
					endOn: model.SearchEndOn,
					state: model.SearchState
					);
				var gridModel = new DataSourceResult
				{
					ExtraData = total,
					Data = outs.Select(x =>
					{
						x.StateName = Enum.GetName(typeof(StockOutStateEnum), x.State);
						x.Total = x.Amount * x.Price;
						return x;
					}),
					Total = outs.TotalCount
				};
				return Json(gridModel);
			}
			else
			{
				var outs = _xJEquipmentStockOutDetailService.GetEquipmentStockOutDetails(
					maintenanceId: model.SearchMaintenanceId,
					equipmentId: model.SearchEquipmentId,
					customerId: customer.Id,
					sno: model.SearchSNo,
					wno: model.SearchWNo,
					name: model.SearchName,
					startOn: model.SearchStartOn,
					endOn: model.SearchEndOn,
					state: model.SearchState,
					pageIndex: command.Page - 1,
					pageSize: command.PageSize);
				var total = _xJEquipmentStockOutDetailService.GetTotal(
					maintenanceId: model.SearchMaintenanceId,
					equipmentId: model.SearchEquipmentId,
					customerId: customer.Id,
					sno: model.SearchSNo,
					wno: model.SearchWNo,
					name: model.SearchName,
					startOn: model.SearchStartOn,
					endOn: model.SearchEndOn,
					state: model.SearchState
					);
				var gridModel = new DataSourceResult
				{
					ExtraData = total,
					Data = outs.Select(x =>
					{
						x.StateName = Enum.GetName(typeof(StockOutStateEnum), x.State);
						return x;
					}),
					Total = outs.TotalCount
				};
				return Json(gridModel);
			}
		}

		[HttpPost]
		public virtual ActionResult Details(DataSourceRequest command, int outId)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageOuts))
				return AccessDeniedKendoGridJson();

			var stockOutDetails = _xJEquipmentStockOutDetailService.GetAllStockOutDetails(outId: outId);

			var gridModel = new DataSourceResult
			{
				Data = stockOutDetails.Select(x =>
				{
					return x;
				}),
				Total = stockOutDetails.Count(),
			};

			return Json(gridModel);
		}

		/// <summary>
		/// 设施设备列表
		/// </summary>
		/// <param name="command"></param>
		/// <param name="planId"></param>
		/// <returns></returns>
		[HttpPost]
		public virtual ActionResult EquipmentList(DataSourceRequest command, EquipmentListModel model)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageOuts))
				return AccessDeniedKendoGridJson();
			//int[] stockIds = _xJEquipmentStockOutDetailService.GetEquipmentIds(model.StockOutId);

			var stocks = _xJEquipmentService.GetAllEquipments4StockOut(
				stockOutId: model.StockOutId,
				categoryId: model.SearchCategoryId,
				placeId: model.SearchPlaceId,
				name: model.SearchName,
				pp: model.SearchManufacturer,
				gg: model.SearchSpecification,
				onlyStock: model.OnlyStock,
				onlyWarn: model.OnlyWarn,
				pageIndex: command.Page - 1,
				pageSize: command.PageSize);
			var gridModel = new DataSourceResult
			{
				Data = stocks.Select(x =>
				{
					x.Breadcrumb = x.GetFormattedBreadCrumb(_xJEquipmentService);
					return x;
				}),
				Total = stocks.TotalCount
			};

			return Json(gridModel);
		}

		public virtual ActionResult DetailUpdate(EquipmentStockOutDetailModel model)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageOuts))
				return AccessDeniedView();

			var detail = _xJEquipmentStockOutDetailService.GetXJEquipmentStockOutDetailById(model.Id) ?? throw new ArgumentException("No stockin detail mapping found with the specified id");
			// 数量增加数量
			int diff = model.Amount - detail.Amount;
			if (diff == 0)
				return new NullJsonResult();
			var equipment = _xJEquipmentService.GetXJEquipmentById(detail.EquipmentId);
			if (null != equipment && !equipment.Deleted)
			{
				if (equipment.Stock <= 0 || equipment.Stock < model.Amount)
				{
					return new NullJsonResult();
				}
				if (diff > 0 && equipment.Stock - equipment.Freeze >= diff)
				{
					equipment.Freeze += diff;
					_xJEquipmentService.UpdateXJEquipment(equipment);
				}
				else if (equipment.Freeze >= diff)
				{
					equipment.Freeze -= diff;
					_xJEquipmentService.UpdateXJEquipment(equipment);
				}
				detail.Amount = model.Amount;
				_xJEquipmentStockOutDetailService.UpdateXJEquipmentStockOutDetail(detail);
			}

			return new NullJsonResult();
		}

		public virtual ActionResult EquipmentUpdate(XJEquipment4StockOut model, int outId)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageOuts))
				return AccessDeniedView();

			var equipment = _xJEquipmentService.GetXJEquipmentById(model.Id);
			if (null == equipment || equipment.Stock <= 0 || equipment.Stock < model.Amount)
				return new NullJsonResult();

			if (model.DetailId > 0)
			{
				var detail = _xJEquipmentStockOutDetailService.GetXJEquipmentStockOutDetailById(model.DetailId);
				if (null != detail)
				{
					detail.Name = model.Name;
					detail.Manufacturer = model.Manufacturer;
					detail.Specification = model.Specification;
					detail.Price = model.Price;
					detail.Amount = model.Amount;
					_xJEquipmentStockOutDetailService.UpdateXJEquipmentStockOutDetail(detail);
				}
			}
			else
			{
				var detail = _xJEquipmentStockOutDetailService.GetXJEquipmentStockOutDetailByOutIdAndEId(stockOutId: outId, equipmentId: model.Id);
				if (null != detail)
				{
					detail.Name = model.Name;
					detail.Manufacturer = model.Manufacturer;
					detail.Specification = model.Specification;
					detail.Price = model.Price;
					detail.Amount = model.Amount;
					_xJEquipmentStockOutDetailService.UpdateXJEquipmentStockOutDetail(detail);
				}
				else
				{
					detail = new XJEquipmentStockOutDetail
					{
						EquipmentStockOutId = outId,
						EquipmentId = model.Id,
						Name = model.Name,
						Manufacturer = model.Manufacturer,
						Specification = model.Specification,
						Price = model.Price,
						Amount = model.Amount,
					};
					_xJEquipmentStockOutDetailService.InsertXJEquipmentStockOutDetail(detail);
				}
			}

			return new NullJsonResult();
		}

		public virtual ActionResult DetailDelete(int id)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageOuts))
				return AccessDeniedView();

			var detail = _xJEquipmentStockOutDetailService.GetXJEquipmentStockOutDetailById(id);
			if (null != detail)
			{
				var equipment = _xJEquipmentService.GetXJEquipmentById(detail.EquipmentId);
				if (null != equipment)
				{
					equipment.Freeze -= detail.Amount;
					_xJEquipmentService.UpdateXJEquipment(equipment);
					_xJEquipmentStockOutDetailService.DeleteXJEquipmentStockOutDetail(detail);
				}
			}

			return new NullJsonResult();
		}

		public virtual ActionResult EquipmentAddPopup(int outId)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageOuts))
				return AccessDeniedView();

			var model = new EquipmentListModel
			{
				StockOutId = outId,
				OnlyStock = true,
			};

			model.AvailableCategories.Add(new SelectMenuModel
			{
				name = "全部",
				id = 0,
				open = true,
			});
			var categorys = _xJEquipmentCategoryService.GetAllCategorys(showHidden: false);
			foreach (var c in categorys)
				model.AvailableCategories.Add(new SelectMenuModel { name = c.Name, id = c.Id, pId = c.PId });
			model.AvailablePlaces.Add(new SelectListItem
			{
				Text = "全部",
				Value = "0"
			});
			var places = _xjPlaceService.GetAllPlaces(showHidden: false);
			foreach (var p in places)
				model.AvailablePlaces.Add(new SelectListItem { Text = p.Name, Value = p.Id.ToString() });
			return View(model);
		}

		[HttpPost]
		[FormValueRequired("save")]
		public virtual ActionResult EquipmentAddPopup(string btnId, string formId, EquipmentListModel model)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageOuts))
				return AccessDeniedView();

			if (model.StockOutId > 0)
			{
				if (model.SelectedProductIds != null)
				{
					var stockOutDetails = _xJEquipmentStockOutDetailService.GetAllStockOutDetails(outId: model.StockOutId).ToList();
					foreach (int id in model.SelectedProductIds)
					{
						if (!stockOutDetails.Any(m => m.Id == id))
						{
							var equipment = _xJEquipmentService.GetXJEquipmentById(id);
							if (equipment != null && equipment.Stock > equipment.Freeze)
							{
								_xJEquipmentStockOutDetailService.InsertXJEquipmentStockOutDetail(new XJEquipmentStockOutDetail
								{
									EquipmentStockOutId = model.StockOutId,
									EquipmentId = equipment.Id,
									Name = equipment.Name,
									Manufacturer = equipment.Manufacturer,
									Specification = equipment.Specification,
									Price = equipment.Price,
									Amount = 1
								});
								// 领用申请时只增加冻结数量，不扣减库存；确认出库时再处理库存
								equipment.Freeze += 1;
								_xJEquipmentService.UpdateXJEquipment(equipment);
							}
						}
					}
				}
			}

			ViewBag.RefreshPage = true;
			ViewBag.btnId = btnId;
			ViewBag.formId = formId;
			return View(model);
		}

		#endregion

		#region Report

		public virtual ActionResult ReportByEquipmentList()
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageReports))
				return Content("");

			var model = new ReportByUserListModel();
			model.AvailableDepartmentMenus.Add(new SelectMenuModel
			{
				name = "全部",
				id = 0,
				open = true,
			});
			model.AvailableUsers.Add(new SelectListItem
			{
				Text = "全部",
				Value = "0"
			});
			var departments = _departmentService.GetAllDepartments(
				pid: 0,
				showHidden: false,
				isMaintenance: true);
			foreach (var d in departments)
				model.AvailableDepartmentMenus.Add(new SelectMenuModel { name = d.Name, id = d.Id, pId = d.PId });

			var users = _customerService.GetAllCustomers(
					customerRoleIds: new int[] { _customerService.GetCustomerRoleBySystemName(SystemCustomerRoleNames.Repairman).Id },
					showHidden: false
				).ToList();
			foreach (var u in users)
			{
				model.AvailableUsers.Add(new SelectListItem
				{
					Text = u.TrueName ?? u.Username,
					Value = u.Id.ToString()
				});
			}
			return View(model);
		}

		public virtual ActionResult ReportByEquipment()
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageReports))
				return Content("");

			return PartialView();
		}

		[HttpPost]
		public virtual ActionResult ReportByEquipments(DataSourceRequest command, ReportByUserListModel model)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageReports))
				return AccessDeniedKendoGridJson();

			int year = 0, month = 0;
			if (model.SearchMonth.HasValue)
			{
				year = model.SearchMonth.Value.Year;
				month = model.SearchMonth.Value.Month;
			}
			var items = _xJEquipmentStockOutService.GetReportByEquipment(
				year: year,
				month: month,
				departmentId: model.SearchDepartId,
				customerId: model.SearchUserId,
				pageIndex: command.Page - 1,
				pageSize: command.PageSize);
			var gridModel = new DataSourceResult
			{
				ExtraData = _xJEquipmentStockOutService.GetTotalByEquipment(
				year: year,
				month: month,
				departmentId: model.SearchDepartId,
				customerId: model.SearchUserId),
				Data = items.Select(x =>
				{
					x.Total = x.Price * x.Amount;
					return x;
				}),
				Total = items.TotalCount
			};

			return Json(gridModel);
		}

		[HttpPost, ActionName("ReportByEquipmentList")]
		[FormValueRequired("exportbyequipmentexcel-all")]
		public virtual ActionResult ExportByEquipmentExcelAll(ReportByUserListModel model)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageReports))
				return AccessDeniedView();

			int year = 0, month = 0;
			if (model.SearchMonth.HasValue)
			{
				year = model.SearchMonth.Value.Year;
				month = model.SearchMonth.Value.Month;
			}
			var items = _xJEquipmentStockOutService.GetReportByEquipment(
				year: year,
				month: month,
				departmentId: model.SearchDepartId,
				customerId: model.SearchUserId);

			try
			{
				foreach (var x in items)
				{
					x.Total = x.Price * x.Amount;
				}
				byte[] bytes = _exportManager.ExportStockOutReportByEquipmentToXlsx(items.Select(x => { x.Total = x.Price * x.Amount; return x; }).ToList());
				return File(bytes, MimeTypes.TextXlsx, "领用设备统计.xlsx");
			}
			catch (Exception exc)
			{
				ErrorNotification(exc);
				return RedirectToAction("ReportByEquipmentList");
			}
		}
		#endregion

		public virtual ActionResult DetailPopup(int eId)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageOuts))
				return AccessDeniedView();

			var model = new EquipmentStockOutListModel
			{
				SearchEquipmentId = eId
			};
			return View(model);
		}

		public virtual ActionResult AddPopup(int maintenanceId)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageOuts))
				return AccessDeniedView();

			var customer = _workContext.CurrentCustomer;
			var model = new EquipmentStockOutModel();
			var stockOut = _xJEquipmentStockOutService.GetStockOutByCustomerId(customer.Id, maintenanceId: maintenanceId);
			if (null != stockOut && !stockOut.Deleted)
			{
				model = new EquipmentStockOutModel
				{
					Id = stockOut.Id,
					MaintenanceId = stockOut.MaintenanceId,
					SNo = stockOut.SNo,
					State = stockOut.State,
					CustomerId = stockOut.CustomerId,
					CreatedOn = stockOut.CreatedOn,
				};
			}
			else
			{
				var maintenance = _xJMaintenanceService.GetXJMaintenanceById(maintenanceId);
				if (null != maintenance)
				{
					var newOut = new XJEquipmentStockOut
					{
						MaintenanceId = maintenanceId,
						SNo = _xJEquipmentStockOutService.GenerateNo(),
						State = (int)StockOutStateEnum.保存,
						CustomerId = customer.Id,
						CreatedOn = DateTime.Now,
					};
					_xJEquipmentStockOutService.InsertXJEquipmentStockOut(newOut);
					model = new EquipmentStockOutModel
					{
						Id = newOut.Id,
						MaintenanceId = newOut.MaintenanceId,
						SNo = newOut.SNo,
						State = newOut.State,
						CustomerId = newOut.CustomerId,
						CreatedOn = newOut.CreatedOn,
					};
				}
			}
			return View(model);
		}

		[HttpPost, ParameterBasedOnFormName("save-continue", "continueEditing")]
		//[FormValueRequired("save")]
		public virtual ActionResult AddPopup(string btnId, string formId, EquipmentStockOutModel model, bool continueEditing)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageOuts))
				return AccessDeniedView();

			if (ModelState.IsValid)
			{
				var stockOut = _xJEquipmentStockOutService.GetXJEquipmentStockOutById(model.Id);
				if (stockOut != null && !stockOut.Deleted)
				{
					stockOut.State = continueEditing ? (int)StockOutStateEnum.保存 : (int)StockOutStateEnum.待审核;
					_xJEquipmentStockOutService.UpdateXJEquipmentStockOut(stockOut);
				}
			}
			ViewBag.RefreshPage = true;
			ViewBag.btnId = btnId;
			ViewBag.formId = formId;
			return View(model);
		}

		public virtual ActionResult ViewPop(int id, int eId)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageOuts))
				return AccessDeniedView();

			var stockOut = _xJEquipmentStockOutService.GetXJEquipmentStockOutById(id);
			if (stockOut == null || stockOut.Deleted)
				//No equipment found with the specified id
				return RedirectToAction("DetailPopup", new { eId });

			var model = new EquipmentStockOutModel
			{
				Id = stockOut.Id,
				SearchEquipmentId = eId,
				MaintenanceId = stockOut.MaintenanceId,
				SNo = stockOut.SNo,
				State = stockOut.State,
				CustomerId = stockOut.CustomerId,
				CreatedOn = stockOut.CreatedOn,
			};
			return View(model);
		}

		public virtual ActionResult AuditPop(int id, int eId)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageOuts))
				return AccessDeniedView();

			var stockOut = _xJEquipmentStockOutService.GetXJEquipmentStockOutById(id);
			if (stockOut == null || stockOut.Deleted)
				//No equipment found with the specified id
				return RedirectToAction("DetailPopup", new { eId });

			var model = new EquipmentStockOutModel
			{
				Id = stockOut.Id,
				SearchEquipmentId = eId,
				MaintenanceId = stockOut.MaintenanceId,
				SNo = stockOut.SNo,
				State = stockOut.State,
				CustomerId = stockOut.CustomerId,
				CreatedOn = stockOut.CreatedOn,
			};
			return View(model);
		}

		[HttpPost, ParameterBasedOnFormName("save-pass", "pass")]
		public virtual ActionResult AuditPop(EquipmentStockOutModel model, bool pass)
		{
			if (!_permissionService.Authorize(StandardPermissionProvider.ManageOuts))
				return AccessDeniedView();

			var stockOut = _xJEquipmentStockOutService.GetXJEquipmentStockOutById(model.Id);
			if (stockOut == null || stockOut.Deleted)
				//No equipment found with the specified id
				return RedirectToAction("DetailPopup", new { eId = model.SearchEquipmentId });

			var customer = _workContext.CurrentCustomer;

			if (ModelState.IsValid)
			{
				var result = _xJEquipmentStockOutService.Out(model.Id, pass, customer);
				if (!result.Result)
				{
					ErrorNotification(result.Msg ?? "不能出库");
					return View(model);
				}
				//activity log
				_customerActivityService.InsertActivity("AuditStockOut", "审核出库记录：{0}", stockOut.Id);

				SuccessNotification("操作成功");
				return RedirectToAction("DetailPopup", new { eId = model.SearchEquipmentId });
			}

			return View(model);
		}

	}
}